package top.wangjiu.reactive.rpc.config;

import io.netty.channel.ChannelOption;
import io.netty.util.AttributeKey;
import lombok.Data;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import top.wangjiu.reactive.rpc.handler.*;
import top.wangjiu.reactive.rpc.registration.ServerRegister;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.*;

@Data
public class ServerConfiguration {

    private InetSocketAddress serverAddress;

    //服务注册器
    private ServerRegister serverRegister;

    /**
     * 实际上netty的读事件处理线程数，在本组件中表示请求接收线程数，如果为0，则为netty默认线程数
     */
    private int requestAcceptThread = 0;

    /**
     * netty只负责接收请求，这个是处理请求的线程数，同样为0则为默认线程数，也就是cpu核数的两倍,
     * 当然也可以自己指定线程池
     */
    private int requestProcessThread = 0;

    private final Map<ChannelOption<Object>, Object> options = new LinkedHashMap();
    private final Map<ChannelOption<Object>, Object> childOptions = new LinkedHashMap();
    private final Map<AttributeKey<Object>, Object> attrs = new ConcurrentHashMap();

    private final Map<Class<?>, Class<? extends RequestHandler<?>>> resultTypeHandlerMap = new HashMap<>();

    private final Class defaultTypeHandler = DefaultRequestHandler.class;

    private Executor requestExecutor;

    //当客户端与服务端在指定时间内没有通讯后断开连接
    private int connectAliveTimeoutSecond = 10;

    public ServerConfiguration(){
        addResultTypeHandler(Mono.class, MonoRequestHandler.class);
        addResultTypeHandler(Flux.class, FluxRequestHandler.class);
        addResultTypeHandler(CompletableFuture.class, FutureRequestHandler.class);
    }

    public <T> void addResultTypeHandler(Class<T> type, Class<? extends RequestHandler<T>> typeHandler){
        resultTypeHandlerMap.put(type,typeHandler);
    }

    public Executor getRequestExecutor() {
        if(requestExecutor==null){
            synchronized (this){
                if(requestExecutor ==null){
                    requestExecutor =  buildDefaultExecutor();
                }
            }
        }
        return requestExecutor;
    }

    private Executor buildDefaultExecutor(){
        int threadCount = requestProcessThread <=0 ? Runtime.getRuntime().availableProcessors() : requestProcessThread;
        return new ThreadPoolExecutor(threadCount, threadCount*2, 5, TimeUnit.MINUTES,
                new LinkedBlockingDeque(),
                new ThreadPoolExecutor.CallerRunsPolicy());
    }

    public <T> Class<? extends RequestHandler<T>> getResultTypeHandler(Class<T> returnType) {
        Class handler = resultTypeHandlerMap.get(returnType);
        if(handler == null){
            handler = defaultTypeHandler;
        }
        return handler;
    }
}
